package com.recharge.common.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by liping on 2018-08-10.
 */
public class MD5Util {

    /**
     * <h2>md5加密</h2>
     *  <p> - 根据ascll码进行升序</p>
     *  <p> - map中value为空的key不进行加密</p>
     *  <p> - 密钥拼接名称为key</p>
     * @param map 加密参数
     * @param privateKey 密钥
     * @return java.lang.String
     */
    public static String md5(Map<String, String> map, String privateKey) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        // 对map集合进行 过滤,排序,拼接
        String beforeSignStr = map.entrySet().stream()
                .filter(e -> !TemplateUtils.isEmpty(e.getValue()))  //过滤
                .sorted(Map.Entry.comparingByKey())  //排序
                .map(e -> e.getKey() + "=" + e.getValue()) //单个key-value拼接
                .collect(Collectors.joining("&")); //多个拼接
        beforeSignStr += "&key=" + privateKey;
        System.out.println("before_sign: "+ beforeSignStr);
        String afterSignStr = "";
        //加密
        try {
//			System.out.println("before_sign: "+beforeSignStr);
            afterSignStr = md5(beforeSignStr, 32);
//			System.out.println("after_sign: "+afterSignStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return afterSignStr;
    }

    /**
     * <h2>md5加密,不自动排序</h2>
     *  <p> - map中value为空的key不进行加密</p>
     *  <p> - 密钥拼接名称为key</p>
     * @param map 加密参数
     * @param privateKey 密钥
     * @return java.lang.String
     */
    public static String md5NoSort(Map<String, String> map, String privateKey) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        // 对map集合进行 过滤,排序,拼接
        String beforeSignStr = map.entrySet().stream()
                .filter(e -> !TemplateUtils.isEmpty(e.getValue()))  //过滤
                .map(e -> e.getKey() + "=" + e.getValue()) //单个key-value拼接
                .collect(Collectors.joining("&")); //多个拼接
        beforeSignStr += "&key=" + privateKey;
        System.out.println("before_sign: "+ beforeSignStr);
        String afterSignStr = "";
        //加密
        try {
//			System.out.println("before_sign: "+beforeSignStr);
            afterSignStr = md5(beforeSignStr, 32);
//			System.out.println("after_sign: "+afterSignStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return afterSignStr;
    }


//    public static void main(String[] args) {
//        Map<String, String> hashMap = new HashMap<>();
//        hashMap.put("userId", "188");
//        hashMap.put("bizId", "201");
//        hashMap.put("ejId", "345kjh3456n");
//        hashMap.put("downstreamSerialno", "2541540");
//        hashMap.put("status", "2");
//        hashMap.put("voucher", "4982344597230");
//        hashMap.put("abc", "");
//        System.out.println(md5(hashMap));
//    }


    public static String md5(String content) throws Exception {
        StringBuffer sb = new StringBuffer();
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(content.getBytes("UTF-8"));
            byte[] tmpFolder = md5.digest();

            for (byte aTmpFolder : tmpFolder) {
                sb.append(Integer.toString((aTmpFolder & 0xff) + 0x100, 16).substring(1));
                //sb.append(Integer.toHexString((aTmpFolder & 0xFF) | 0x100).substring(1, 3));
            }

            return sb.toString();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
            throw new Exception("无法生成指定内容的MD5签名", ex);
        }
    }

    public static String md5(String content, int length) throws Exception {
        StringBuilder sb = new StringBuilder();
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(content.getBytes("UTF-8"));
            byte[] tmpFolder = md5.digest();

            for (byte aTmpFolder : tmpFolder) {
                sb.append(Integer.toString((aTmpFolder & 0xff) + 0x100, 16).substring(1));
                //sb.append(Integer.toHexString((aTmpFolder & 0xFF) | 0x100).substring(1, 3));
            }

//            /*
//               下边的运算就是自己添加的一些二次小加密，记住这个千万不能弄错乱，
//                   否则在解密的时候，你会发现值不对的（举例：在注册的时候加密方式是一种，
//                在我们登录的时候是不是还需要加密它的密码然后和数据库的进行比对，但是
//            最后我们发现，明明密码对啊，就是打不到预期效果，这时候你就要想一下，你是否
//             有改动前后的加密方式）   
//            */
//            int i;
//            for (int offset = 0; offset < digest.length; offset++) {
//                i = digest[offset];
//                if (i < 0)
//                    i += 256;
//                if (i < 16)
//                    sb.append(0);
//                sb.append(Integer.toHexString(i));//通过Integer.toHexString方法把值变为16进制
//            }
            return sb.toString().substring(0, length);//从下标0开始，length目的是截取多少长度的值
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
            throw new Exception("无法生成指定内容的MD5签名", ex);
        }
    }
}
